.. _Actions API: ############################################ Краткое описание Actions API ############################################ ActionsAPI - это конфигурация действий в формате JSON. Сами действия (actions) - это то, что необходимо выполнить на стороне клиента (фронтенда) по инициативе пользователя (как правило, при нажатии кнопки, выборе пункта меню и т.п.). В рамках JSON-терминологии, действие - это объект, содержащий свойства, необходимые для корректного запуска действия. ******************************************************************** Варианты использования Actions API ******************************************************************** Actions API используется: * внутри системы, * при настройке элементов сайдбаров, * при настройки действий элементов формы: * кнопка - действия при нажатии на кнопку формы, * иконка - действия при нажатии на иконку формы .. note:: В дальнейшем использование API будет расширено ******************************************************************** Формат описания действия ******************************************************************** Объект описания действия содержит следующие обязательные и не обязательные свойства: * **name** - *обязательное*. Имя источника действия. Имя источника должно соответствовать одному из доступных, реализованных на клиенте, действия. Перечень доступных действий приведён ниже. * **params** - *не обязательное*. JSON-объект, описывающий параметры для конкретного действия. Для каждого действия может быть свой специфический набор параметров. * **done** - *не обязательное*. Объект-действие или массив объектов-действий. Описание действия которое должно быть выполнено при удачном завершении предыдущего действия. Результат выполенения предыдущего дейсствия передаётся в текущее в виде входного параметра. Порядок использования входного параметра описан в документации к действию. .. note:: Если свойство не задано, то при успешном завершении предыдущего действия не будет больше вызвано ни каких дополнительных действий. * **cancel** - *не обязательное*. Объект-действие или массив объектов-действий. Описание действия, которое должно быть выполнено в случае отмены предыдущего действия пользователем. Не все действия могут быть отменены пользователем, поэтому в таких действиях описание свойства **cancel** не имеет смысла. .. note:: Если свойство не задано, то будет выполнено действие по умолчанию- **notify**, которое выведет пользователю сообщение об отмене действия. Если необходимо "заглушить" выполнение действия при отмене, то нужно установить свойство в значение **false**. * **fail** - *не обязательное*. Объект-действие или массив объектов-действий. Описание действия, которое должно быть выполнено в случае сбоя (ошибки) при выполнении предыдущего действия. .. note:: Если свойство не описано, но при выполнении предыдущего действия произошёл сбой, то будет выполнено действие по умолчанию - **notify**, которое выведет пользователю сообщение о неудачном выполнении действия. Если необходимо "заглушить" выполнение действия при ошибке, то нужно установить свойство в значение **false** ******************************************************************** Цепочки действий ******************************************************************** Можно описать как однократное действие, так и выстраивать цепочки действий по описанным ниже правилам. Если описание действий - это массив объектов-описаний, то действия будут выполнены последовательно друг за другом: сначала первое в массиве, затем второе - и т.д. Кроме массива, можно строит цепочку действий, описывая дополнительные действия в параметрах **done**, **cancel**, **fail**. В свою очередь, действие, описываемое в любом из этих параметров, тоже может содержать вложенные действия, описанные в одноимённых параметрах. Таким образом, можно строить цепочку неограниченных вложенных действий. Кроме того, сами параметры **done**, **cancel**, **fail** могут содержать не только одинарное действие, но и массив действий. ******************************************************************** Перечень доступных действий ******************************************************************** ======================================================================== Действие "**store**" ======================================================================== .. DANGER:: Не реализовано в коде Действие, которое будет вызывать действие в хранилище (**store**) приложения. **Параметры действия:** * **name** - имя действия в хранилище. Например: **"form/saveItem"**. * **payload** - параметры, которые будут переданы в действие хранилища. ======================================================================== Действие "**dialog**" ======================================================================== .. warning:: Частично реализовано в коде Открывает диалогове окно с формой, где пользователь может выбрать значения. При закрытии диалогового окна или при нажатии кнопки "Отмена" будет выполнено действие **cancel**, при нажатии кнопки "ОК" - действие **done**. *Возвращаемое значение* При нажатии кнопки "ОК" действие возвращает объект данных в формате **{ "имя_поля": значение }**, где "имя_поля" - свойство **name** каждого поля ввода формы, а "значение" - значение этого поля. *Параметры действия:* * **title** - заголовок диалогового окна. * **subtitle** - подзаголовок диалогового окна. * **form** - описание формы (см. раздел [[Описание ActionsAPI#Описание формы в действиях|Описание формы в действиях]]). ======================================================================== Действие "**notify**" ======================================================================== Вывод всплывающего сообщения пользователю. При описании действия свойства **done**, **cancel**, **fail** не имеют смысла. *Параметры действия:* * **type** - тип всплывающего сообщения: **"info"**, **"warning"**, **"error"**. * **message** - сообщение. Может быть *строкой*, *объектом* или *массивом* строк и/или объектов с описанием в формате "Quasar Notify":https://v1.quasar.dev/quasar-plugins/notify#notify-api. Одно исключение: позицию вывода поменять нелья, она соответствует соглашениям, принятым в приложении. В качестве строки **message**, либо свойства **message** объекта **message**, а также свойства **caption** объекта **message** можно передать ключ локализации, тогда он будет автоматически преобразован в локализованную строку. ======================================================================== Действие "**change_data**" ======================================================================== Изменение свойств данных. Данные - это объект или массив объектов. Действие подразумевает, что необходимо изменить одно или несколько свойств в объекте, либо в каждом объекте массива. *Параметры действия* * **source** - источник данных. Может принимать значения: * **context** - источником данных служит контекст приложения; * **input** - источник данных - это входной параметр действия (переданный, например, из предыдущего действия). * **описание объекта** - непосредственное описание объекта со свойствами и значениями, который будет использован в качестве входного параметра. Параметр **source** может быть опущен, тогда в качестве источника данных будут использоваться данные контекста, если это первое действие в конфигурации, и выходные данные предыдущего действия, если это вложенное действие. * **properties** - массив имён свойств в объекте источнике, которые попадут в результирующий объект. Здесь можно не указывать свойства, описанные во вложенных параметрах **values**, так как они будут включены в результирующий объект в любом случае. Если свойство опущено, то будут включены все свойства входного объекта. Если свойство содержит пустой массив, то в выходные данные будут включены только свойства, описанные во вложенных параметрах **values**. Если во входных данных есть свойство с именем "**id**", то оно будет включено в выходные данные в любом случае. * **values** - конфигурация значений на которые будут заменены значения в источнике данных. Содержит следующие вложенные параметры: * **object** - объект вида свойство-значение, в котором свойство должно соответствовать имени изменяемого значения в источнике данных; * **form** - форма, в которой будут установлены значения пользователем. Описание формы приведено в :numref:`actionsAPIinForms`. После выбора значений в форме, эти значения будут возвращены в виде объекта вида свойство-значение. Параметр **values** позволяет указывать как отдельно один из вложенных параметров **object** или **form**, так и их вместе. При этом, если какие-либо из изменяемых свойств в обоих параметрах совпадают, то приоритет отдаётся свойствам, полученным из формы. Следует иметь в виду, что при открытии формы (если данные получаются в том числе и из формы) возможна отмена операции при нажатии на кнопку "Отмена" формы. В этом случае будет отменено всё действие целиком, даже если параметр **values.object** тоже указан в настройках действия. ======================================================================== Действие "**save_data**" ======================================================================== Сохранение данных в схеме на сервере. *Параметры действия* * **source** - источник данных. Может принимать значения: ** **context** - источником данных служит контекст приложения; ** **input** - источник данных - это входной параметр действия (переданный, например, из предыдущего действия). Параметр **source** может быть опущен, тогда в качестве источника данных будут использоваться данные контекста, если это первое действие в конфигурации, и выходные данные предыдущего действия, если это вложенное действие. * **schema** - идентификатор схемы, для которой необходимо сохранить данные. * **mode** - - режим сохранения данных в схеме. Может принимать значения **create** или **update**. По умолчанию (если параметр опущен, либо указано некорректное значение) используется режим **update**. ======================================================================== Действие "**message**" ======================================================================== Отправляет сообщение в контекст приложения, которое может быть обработано текущим компонентом приложения. Действие предназначено для обратной связи с компонентами приложения, которые умеют реагировать на сообщения, отсылаемые действием. *Параметры действия* * **message** - имя сообщения. *Описание имён сообщений и компонентов, которые могут их обработать* * **refresh** - Работает в консоли. При получении этого сообщения консоль обновляет данные. ======================================================================== Действие "**create_related_data**" ======================================================================== Служит для создания новых связанных данных текущей формы. Запуск действвия возможен только для формы, если для формы существуют настройки связей и если форма не открыта для создания записи. *Параметры действия* * **relation_name** - имя конфигурации связанных данных, заданное в настройках формы. * **entity_type_key** - для сложных связей - ключ в объекте **relations** настроек вложенных связей. Пример настройки для пункта панели инструментов: :: { "action": { "source": "ActionsAPI", "config": { "name": "create_related_data", "params": { "relation_name": "form_rel_data_assets", "entity_type_key": "9000" } } } } .. ======================================================================== Действие "**script**" ======================================================================== .. DANGER:: Не реализовано в коде Запускает внешний JS-скрипт. ======================================================================== Действие "**tramsform**" ======================================================================== .. DANGER:: Не реализовано в коде TODO действие должно применять st трансформации данных .. _actionsAPIinForms: ******************************************************************** Описание формы в действиях ******************************************************************** Некоторые действия могут работать с формой для взаимодействия с пользователем. Для таких действий требуется описать параметры формы в одном из свойств действия. Описание формы включает свойства: * **title** - заголовок формы (может являться идентификатором локализации). * **data** - объект, описывающий работу с данными формы. * **elements** - массив, описывающий конфигурацию визуальных элементов формы. Объект **data** включает следующие параметры: * **schema** - ID схемы для формы. Из описания схемы могут браться параметры для элементов формы, а из самой схемы - данные для отображения на форме. Массив **elements** - содержит объекты со следующими возможными параметрами: * **id** - идентификатор элемента. Как правило, для внутреннего использования. Если не задан, то будет использован либо **form_id**, либо ID поля схемы из метаданных схемы, если такое поле есть для этого элемента, либо сгенерирован UUID. * **name** - имя элемента. Может иметь значение при работе с данными, когда соответствует имени поля в записях данных. Если свойство не задано, то будет использовано либ имя поля схемы, либо ID поля схемы, либо будет равно свойству **id**, если ни одно из предыдущих не определено. * **field_id** - ID поля схемы, которое должно соответствовать элементу. * **field_name** - Имя поля схемы, которое должно соответствовать элементу. Может быть использовано, если не задан **field_id**. * **type** - тип визуального элемента (перечень типов см. ниже). Тип может быть определён автоматически исходя из соответствующего поля схемы (если оно определено и найдено в схеме). Если тип не удалось определить, то по умолчанию применяется тип **input**. * **label** - подпись элемента. Может быть идентификатором локализации. Кроме того, подпись может быть определена автоматически исходя из **field_id**, либо поля схемы (если оно определено и найдено в схеме). Если подпись не удалось определить, то она не отображается. * **options** - дополнительный массив опций для списка выбора, который может быть задан, если тип элемента - **select**. Массив опций может быть как массивом строк, так и массивом объектов с ключами **value** и **label**. Массив опций может быть также определён автоматически, если для элемента задано и найдёно поле в схеме и его тип - **enum**. На основе локализованных значений **enum**, если локализация для них задана, строится массив опций. Перечень допустимых типов элементов формы: * **input** - простое поле ввода текста. * **textarea** - расширенное (многострочное) поле ввода текста. * **select** - список выбора. Для списка выбора может быть задан параметр **options** для элемента. ******************************************************************** Условия ******************************************************************** Условия применяются для условного выполнения действия и для условного отображения пункта меню при настройке сайдбаров (поле **conditions**). Фомат описания условий одинаковый, как для действий, так и для сайдбара ======================================================================== Описание условий ======================================================================== Условие описывается в формате JSON в виде объекта, который содержит свойства: * **source_value** - источник входных данных которые будут проверятся. Строка, которая может принимать значения: * **input** - будут проверятся входные данные действия. * **context** - будут проверятся данные контекста. По умолчанию **source_value** для сайдбара - **context**, для действий - **input**. Поэтому значение можно опускать в обоих случаях. * **typeof** - проверяет, удовлетворяют ли входные данные заданному типу. Значение свойства - строка с именем типа или массив строк с именами типов. Если значение - массив строк, то проверяется соответствие хотябы одному из типов. Для проверки соответствия входных данных могут быть использованы следующие имена типов: * **object** - объект; * **not_object** - любой тип, кроме объекта, **null** и **undefined**; * **number** - число; * **not_number** - любой тип, кроме числа, **null** и **undefined**; * **array** - массив; * **not_array** - любой тип, кроме массива, **null** и **undefined**; * **array_of_objects** - массив объектов (каждый элемент в массиве должен быть объектом); * **string** - строка; * **not_string** - любой тип, кроме строки, **null** и **undefined**; * **boolean** - чётко логический тип (конкретно **true** или **false**); * **not_boolean** - любой не логический тип (не **boolean**) и не **null**, и не **undefined**; * **null** - null; * **not_null** - не **null** и не **undefined**; * **undefined** - значение не определено. ******************************************************************** Использование Actions API в элементах форм ******************************************************************** Actions API позволяет выполнять действия в компонентах формы: * кнопки * иконки .. note:: Настройка действий выполняется в виде JSON в поле **Действия** Пример действия в формате JSON: :: { "click": { "type": "ActionsAPI", "config": { "name": "change_data", "params": { "source": {}, "values": { "form": { "title": "Создать категорию", "elements": [ { "type": "input", "name": "category", "label": "Введите наименование категории" } ] } } }, "done": { "name": "save_data", "params": { "schema": "ref_task_categories" } } } } } .. где: * **click** - тип действия (обязательно) * **"type": "ActionsAPI"** - указание на использование Actions API * **config** - JSON описания действия в формате Actions API ******************************************************************** Менеджер действий ******************************************************************** Менеджер действий (**ActionManager**) - это единственный компонент, который необходимо использовать для запуска действий из кода приложения. Для доступа к менеджеру действий необходимо использовать метод **getActionManager**, передав в него экземпляр приложения. Например, из Vue-компонента приложения это можно сделать следующим образом: .. code-block:: javascript import { getActionManager } from '**/utils/ActionManager' export default { methods: { runActions () { const actionManager = getActionManager(this) } } } .. Через экземпляр приложения Менеджер действий получает доступ ко всем необходимым ресурсам для работы - контексту, репозиториям, стору, методам локализации и т.д. ======================================================================== Запуск действий ======================================================================== Для запуска действий Менеджер действий имеет асинхронный метод **run**, в который передаётся конфигурация действий. Результат выполнения цепочки действий возвращается из метода **run**. Это результат можно использовать при необходимости. .. code-block:: javascript import { getActionManager } from '**/utils/ActionManager' export default { methods: { async runActions (actionsConfig) { const actionManager = getActionManager(this) const result = await actionManager.run(actionsConfig) } } } .. Следует иметь в виду, что входным параметром для первого действия (или первых действий в массиве действий) являются данные контекста. Поэтому, если необходимо передать конкретные начальные данные в действия, то их необходимо сначала сохранить в контексте: .. code-block:: javascript import { getActionManager } from '**/utils/ActionManager' export default { methods: { async runActions (actionsConfig) { this.$context.setData(this.someData) const actionManager = getActionManager(this) await actionManager.run(actionsConfig) } } } .. ======================================================================== Проверка условий ======================================================================== Менеджер действий содержит метод **checkConditions** для проверки условий (**conditions**), которые определены для пункта меню сайдбара. Метод возвращает логическое значение (**true**/**false**), являющееся результатом проверки. Использовать результат проверки можно по желанию разработчика. В метод **checkConditions** помимо конфигурации условий можно передать данные, на основе которых будет производится проверка. Если данные ни какие не передаются, либо передаётся **null** или **undefined**, то будут использованы данные контекста. В качестве примера можно привести использоание метода **checkConditions** в компоненте контекстного меню для решения отображать элемент меню, или нет: .. code-block:: javascript group.items.forEach(item => { if (this.actionManager.checkConditions(item.conditions)) { const menuItem = getNewItem(item) menuItem.action = item.item groupMenu.push(menuItem) } }) .. ******************************************************************** Пример json описания действия ******************************************************************** ======================================================================== Пример оповещения ======================================================================== :: { "action": { "source": "ActionsAPI", "config": { "name": "notify", "params": { "type": "info" }, "done": [ { "source": "ActionsAPI", "config": { "name": "save_data", "params": { "source": "context", "schema": "schm024" } } }, { "source": "ActionsAPI", "config": { "name": "dialog", "params": { "form": { "data": {}, "elements": [ { "id": "TEST_ID" }, { "id": "d152affe-7ee4-3472-861e-8d76b43e5783", "type": "input" }, { "id": "222275b1-f05c-33e4-b9d7-6a1b77a980d7", "type": "input" } ] } } } }, { "source": "ActionsAPI", "config": { "name": "message", "params": {}, "done": [ { "source": "ActionsAPI", "config": { "name": "notify", "params": { "type": "info" } } } ] } } ], "fail": [ { "source": "ActionsAPI", "config": { "name": "create_related_data", "params": {} } }, { "source": "ActionsAPI", "config": { "name": "notify", "params": {} } }, { "source": "ActionsAPI", "config": { "name": "create_related_data", "params": {}, "cancel": [ { "source": "ActionsAPI", "config": { "name": "save_data", "params": {} } } ] } } ] } } } .. ======================================================================== Пример изменения данных ======================================================================== :: "name": "change_data", "params": { "properties": [], "values": { "form": { "title": "schemaseditor_admFrmslct_label", "data": { "schema": "schm001" }, "elements": [ { "field_name": "priority" } ] } } }, "done": { "name": "save_data", "params": { "schema": "incidents" }, "done": [ { "name": "message", "params": { "message": "refresh" } }, { "name": "notify", "params": { "message": "data_refresh_success_label" } } ] } } .. ======================================================================== Пример описания действия при нажатии кнопки на форме ======================================================================== :: { "click": { "type": "ActionsAPI", "config": { "name": "change_data", "params": { "source": {}, "values": { "form": { "title": "Создать категорию", "elements": [ { "type": "input", "name": "category", "label": "Введите наименование категории" } ] } } }, "done": { "name": "save_data", "params": { "schema": "ref_task_categories" } } } } } .. где: * **click** - тип действия (для кнопок и иконок поддерживается click. * **type** - ActionsAPI указание типа обработчика действия * **config** - описание действия в формате Actions API ======================================================================== Пример описания действия при нажатии строки таблицы на форме ======================================================================== :: { "row-click": { "type": "ActionsAPI", "config": {} } } .. где: * **row-click** - тип действия (для таблицы на форме поддерживаются row-click и row-dblclick. * **type** - ActionsAPI указание типа обработчика действия * **config** - описание действия в формате Actions API ======================================================================== Пример описания действия при подстановке полей в форме ======================================================================== Описание действия компонента формы :: { "onLoad": { "form_field": "in_009_031", "schema": "people", "field": "full_name" } } .. где: * onLoad - действие загрузки формы * form_field - значение поле формы, используемое в качестве идентификатора для загрузки данных другой схемы * schema - схема данных из которой будут подгружаться данные в поле. * field - поле сторонней схемы из которой будут загружаться данные в схему. .. warning:: Формат имеет временный характер, в дальнейшем действие будет приведено в соответствии со стандартами Actions API ======================================================================== Пример описания действия открытия связанной формы в действии формы ======================================================================== Описание действия формы :: {"click":{"name":"showRelatedForm","type":"emit","payload":{"field_id":"console_card_004_header_01"}}} .. .. warning:: Формат имеет временный характер, в дальнейшем действие будет приведено в соответствии со стандартами Actions API